package com.personal.system.service.impl.approve;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.personal.common.result.Result;
import com.personal.model.system.SysUser;
import com.personal.system.config.SecurityUtil;
import com.personal.system.domain.ApprovalProcessConstants;
import com.personal.system.domain.CostQuoteRules;
import com.personal.system.entity.approval.*;
import com.personal.system.exception.GlobalException;
import com.personal.system.mapper.act.ApproveLogMapper;
import com.personal.system.mapper.act.CostQuoteRulesMapper;
import com.personal.system.service.approve.ApproveDetailService;
import com.personal.system.service.approve.ApproveProcessCallBack;
import com.personal.system.service.approve.ApproveWorkService;
import com.personal.system.service.approve.CostQuoteRulesService;
import com.personal.system.service.sys.AutoIncrementCodeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CostQuoteRulesServiceImpl extends ServiceImpl<CostQuoteRulesMapper, CostQuoteRules>
        implements CostQuoteRulesService, ApproveProcessCallBack {

    @Resource
    private ApproveDetailService detailService;
    @Resource
    private SecurityUtil securityUtil;
    @Resource
    private ApproveWorkService approveService;
    @Resource
    private ApproveLogMapper approveLogMapper;
    @Resource
    private AutoIncrementCodeService codeService;

    @Override
    public void addCost(CostQuoteRules quoteRules) throws Exception {
        if (StrUtil.isBlank(quoteRules.getRuleId())){
            String id = UUID.fastUUID().toString(true);
            quoteRules.setRuleId(id);
            quoteRules.setRuleState("01");
            String gz = codeService.generateCode("GZ", DateUtil.format(DateUtil.date(),"yyMMdd"), 5);
            quoteRules.setRuleNo(gz);
            quoteRules.setCreator(securityUtil.getUserName());
            quoteRules.setUpdater(securityUtil.getUserName());
            this.save(quoteRules);
        } else {
            quoteRules.setUpdater(securityUtil.getUserName());
            quoteRules.setUpdateTime(new Date());
            this.updateById(quoteRules);
        }

    }

    @Override
    public void submitApprove(List<CostQuoteRules> ids) {
        ApproveVo submitApproveVo = new ApproveVo();
        String ruleClassCode = ApprovalProcessConstants.RuleClassEnum.RULE_CLASS_20.getCode();
        String approvalModule = ApprovalProcessConstants.RuleClassEnum.RULE_CLASS_20.getType();
        submitApproveVo.setRuleClass(ruleClassCode);
        submitApproveVo.setApprovalModule(approvalModule);
        String bus = ids.stream().map(e -> e.getRuleId()).collect(Collectors.joining(","));
        submitApproveVo.setBusinessIds(bus.split(","));
        SysUser user = securityUtil.getUser();
        submitApproveVo.setUserId(user.getId());

        String[] split = user.getDeptId().toString().split(",");
        submitApproveVo.setDepartmentIdList(Arrays.asList(split));

        approveService.submitApprove(submitApproveVo);
    }

    @Override
    public void approve(Map<String, Object> params) {
        String radio = params.get("radio").toString();
        String opinion = params.get("opinion").toString();
        String[] ids = ArrayUtil.toArray((ArrayList)params.get("ids"),String.class);
        ApproveVo approveVo = new ApproveVo();
        if ("01".equals(radio)) {
            approveVo.setApprovalResult("01");
        } else {
            approveVo.setApprovalResult("00");
        }
        approveVo.setApprovalComment(opinion);
        approveVo.setBusinessIds(ids);
        approveVo.setApprovalModule("01");
        approveVo.setRuleClass("20");
        approveVo.setUserId(securityUtil.getUserId()+"");

        approveService.approve(approveVo);
    }

    @Override
    public void addSign(Map<String, Object> params) {
        log.info("进入到加签功能!{}",params);
        List<String> ids = (List<String>)params.get("ids");
        String radioSign = params.get("radioSign").toString();
        List<String> signRens = (List<String>)params.get("signRens");
        if (CollUtil.isEmpty(signRens)) throw new GlobalException(404,"加签人员不能为空!");

        List<CostQuoteRules> rules = this.list(Wrappers.lambdaQuery(CostQuoteRules.class).in(CostQuoteRules::getRuleId, ids));
        if (CollUtil.isEmpty(rules) || rules.size() != ids.size()) throw new GlobalException(404,"存在无效数据!");
        List<String> taskIds = new ArrayList<>();
        Long userId = securityUtil.getUserId();

        for (CostQuoteRules rule : rules) {
            String ruleId = rule.getRuleId();
            String ruleNo = rule.getRuleNo();

            ApproveDetail detail = detailService.getOne(Wrappers.lambdaQuery(ApproveDetail.class)
                    .eq(ApproveDetail::getApproveNo, ruleId).eq(ApproveDetail::getApprovalStatus, "02"));
            if (null == detail) throw new GlobalException(404,"找不到该业务的审批实例!");
            taskIds.add(genTaskId(detail));
            String approverType = detail.getApproverType();
            String approver = detail.getApprover();

            if ("01".equals(approverType)) {
                if (userId != Long.valueOf(approver)){
                    throw new GlobalException(404,"加签只能是当前审批的人!");
                }
            } // 如果部门或角色就用approver对比
        }
        // 创建加签对象
        AddSignVo addSignVO = new AddSignVo();
        addSignVO.setBusinessIds(ids);
        addSignVO.setOperationUser(userId.toString());
        addSignVO.setAddSignDirection(radioSign);
        List<ApproveDetail> approveDetails = new ArrayList<>();
        for (String signRen : signRens) {
            ApproveDetail approveDetail = new ApproveDetail();
            approveDetail.setApproverType("01");
            approveDetail.setApprover(signRen);
            approveDetails.add(approveDetail);
        }
        addSignVO.setApproveDetails(approveDetails);
        // 批量加签
        detailService.batchAddSign(addSignVO);
        log.info("加签修改完成,更新单据审批信息");
        // 回显当前审核人数据更新主表
        for (CostQuoteRules item : rules) {
            String quoteId = item.getRuleId();
            LambdaQueryWrapper<ApproveDetail> eq = Wrappers.lambdaQuery(ApproveDetail.class).eq(ApproveDetail::getApproveNo, quoteId).eq(ApproveDetail::getApprovalStatus, "02");
            ApproveDetail appDetail = detailService.getOne(eq);
            CostQuoteRules record = new CostQuoteRules();
            record.setRuleId(quoteId);
            record.setProcessStep(appDetail.getApprover());
            record.setAuditType(appDetail.getApproverType());
            record.setAuditUserId(appDetail.getApprover());
            record.setAuditName(appDetail.getApproverName());
            this.updateById(record);
        }

    }

    private String genTaskId(ApproveDetail detail) {
        String taskid = "GZSP" + detail.getApproveNo() + detail.getApprovalSort();
        if ("02".equals(detail.getAddSignType())) {
            taskid = taskid + "_" + detail.getApprovalSort();
        }
        return taskid;
    }

    @Override
    public List<ApproveLog> findApproval(String ruleId) {
        LambdaQueryWrapper<ApproveLog> qw = new LambdaQueryWrapper<>();
        qw.eq(ApproveLog::getBusinessId,ruleId);
        qw.eq(ApproveLog::getRuleClass, "20");
        qw.eq(ApproveLog::getType, "02");
        qw.orderByDesc(ApproveLog::getCreateTime);

        return approveLogMapper.selectList(qw);
    }

    @Override
    public Result submitForProcess(BusinessApproveVo businessApproveVo) {
        String[] quoteIdArray = businessApproveVo.getBusinessIds();

        for (String ruleId : quoteIdArray) {
            ApproveDetail approve = businessApproveVo.getApproveDetailByBusinessId(ruleId);
            CostQuoteRules rule = new CostQuoteRules();
            rule.setRuleId(ruleId);
            if (approve != null) {
                rule.setAuditUserId(approve.getApprover());
                rule.setAuditName(approve.getApproverName());
                rule.setAuditType(approve.getApproverType());
                rule.setProcessStep(approve.getApprover());
                rule.setProcessStepCount(String.valueOf(approve.getApprovalSort()));
            }
            rule.setRuleState("02");
            rule.setUpdater(businessApproveVo.getUserId());
            rule.setUpdateTime(new Date());

            this.updateById(rule);
        }

        return Result.ok();
    }

    @Override
    public Result rejectedForProcess(BusinessApproveVo businessApproveVo) {
        String[] businessIds = businessApproveVo.getBusinessIds();
        for (String businessId : businessIds) {
            // 保存审批记录
            CostQuoteRules rule = new CostQuoteRules();
            rule.setRuleId(businessId);
            rule.setProcessStep(StringUtils.EMPTY);
            rule.setProcessStepCount(StringUtils.EMPTY);
            rule.setAuditUserId(StringUtils.EMPTY);
            rule.setAuditName(StringUtils.EMPTY);
            rule.setAuditType(StringUtils.EMPTY);
            rule.setUpdater(businessApproveVo.getUserId());
            rule.setUpdateTime(new Date());
            rule.setRuleState("05");

            this.updateById(rule);
        }
        return Result.ok();
    }

    @Override
    public Result completedForProcess(BusinessApproveVo businessApproveVo) {
        String[] businessIds = businessApproveVo.getBusinessIds();
        Date now = new Date();
        // 保存审批记录
        for (String businessId : businessIds) {
            CostQuoteRules rule = new CostQuoteRules();
            rule.setRuleId(businessId);
            rule.setProcessStep(StringUtils.EMPTY);
            rule.setProcessStepCount(StringUtils.EMPTY);
            rule.setAuditUserId(StringUtils.EMPTY);
            rule.setAuditName(StringUtils.EMPTY);
            rule.setAuditType(StringUtils.EMPTY);
            rule.setUpdateTime(now);
            rule.setRuleState("03");

            this.updateById(rule);

            log.info("成本报价审批完成 ruleId={}", businessId);
        }
        return Result.ok();
    }

    @Override
    public Result modifyPendUserForProcess(BusinessApproveVo businessApproveVo) {
        String[] businessIds = businessApproveVo.getBusinessIds();
        for (String businessId : businessIds) {
            CostQuoteRules rule = new CostQuoteRules();
            rule.setUpdater(businessApproveVo.getUserId());
            rule.setUpdateTime(new Date());
            rule.setRuleId(businessId);
            ApproveDetail delayApproveDetail = businessApproveVo.getApproveDetailByBusinessId(businessId);
            if (delayApproveDetail != null) {
                rule.setProcessStep(delayApproveDetail.getApprover());
                rule.setAuditUserId(delayApproveDetail.getApprover());
                rule.setAuditName(delayApproveDetail.getApproverName());
                rule.setAuditType(delayApproveDetail.getApproverType());
                rule.setProcessStepCount(String.valueOf(delayApproveDetail.getApprovalSort()));
                this.updateById(rule);
            }
        }
        return Result.ok();
    }

    @Override
    public ApprovalProcessConstants.RuleClassEnum getRuleClassEnum() {
        return ApprovalProcessConstants.RuleClassEnum.RULE_CLASS_20;
    }

    @Override
    public String getAuditRuleByBusiness(String businessId) {
        CostQuoteRules rules = this.getById(businessId);

        return rules.getCompId();
    }
}
